using System;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.IO;
using System.Resources;

namespace ELS.Configuration
{
	#region Configuration
	/// <summary>
	/// Represents the configuration settings applicable to a particular computer, application, or resource.
	/// </summary>
	public class Configuration : ConfigurationObjectBase
	{
		#region variables
		private string _name = null;
		private ConfigurationSectionCollection _sections = null;
		#endregion variables

		#region constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="ELS.Configuration.Configuration"/> class with the specified XML data.
		/// </summary>
		/// <param name="xml">String containing the XML data to load.</param>
		public Configuration( string xml )
		{
			Load ( xml );
		}
		#endregion constructors

		#region public properties

		/// <summary>
		/// Gets or sets a collection of sections defined by this configuration.
		/// </summary>
		public ConfigurationSectionCollection Sections
		{
			get { return _sections;  }
			set { _sections = value; }
		}
		
		/// <summary>
		/// Gets the name of the configuration.
		/// </summary>
		public override string Name
		{
			get { return _name; }
		}
		#endregion public properties

		#region public functions

		/// <summary>
		/// Loads the specified XML data.
		/// </summary>
		/// <param name="xml">String containing the XML data to load.</param>
		public void Load ( string xml )
		{
			if ( xml == null )
				throw new ArgumentNullException ( "xml", "xml source cannot be null" );
	
			XmlDocument doc = new XmlDocument();
			doc.LoadXml( xml );
			XmlNamespaceManager nsmgr = new XmlNamespaceManager( doc.NameTable );
			nsmgr.AddNamespace( Constants.NAMESPACE_PREFIX, Constants.NAMESPACE_URI );

			_name = doc.DocumentElement.Attributes["name"].InnerText;

			_sections = new ConfigurationSectionCollection( this );
			XmlNodeList nodeList = doc.SelectNodes("./ns:configuration/ns:sections/ns:section", nsmgr);
			ConfigurationSection configSection = null;
			foreach(XmlNode node in nodeList)
			{
				configSection = ConfigurationSection.FromXml( node.OuterXml );
				configSection.Parent = this;
				this.Sections.Add( configSection );
			}
		}

		/// <summary>
		/// Gets the section with the specified name.
		/// </summary>
		/// <param name="name">the name of the section to lookup.</param>
		/// <returns>a <see cref="ELS.Configuration.ConfigurationSection"/> object.</returns>
		public ConfigurationSection GetSection ( string name )
		{
			string[] arrSections = name.Split(new char[]{'.'});
			if (arrSections != null )
			{
				ConfigurationSection result = this.Sections[ arrSections [0] ];
				for(int i=1; i < arrSections.Length; i++ )
				{
					string s = arrSections [i] ;
					if ( s != null && s.Length > 0 )
						result = result.Sections[ s ];

					if ( result == null )
						return null;
				}
				return result;
			}
			return null;
		}


		/// <summary>
		/// Returns the XML representation of the data stored in the <see cref="ELS.Configuration.Configuration"/>.
		/// </summary>
		/// <returns>A string that is a representation of the data stored in the <see cref="ELS.Configuration.Configuration"/>.</returns>
		public string GetXml()
		{
			StringBuilder sb = new StringBuilder();
			XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb));
			writer.WriteStartElement("configuration");
			writer.WriteAttributeString("name", Name);
			foreach( ConfigurationSection section in Sections )
			{
				writer.WriteRaw(section.GetXml());
			}
			writer.WriteEndElement();
			
			return sb.ToString();
		}
		#endregion public functions
	}
	#endregion Configuration
}
